import os
import sys
import time
import argparse

# 定义 Qt 安装目录
QT_INSTALL_DIR = [
    '/usr/lib/aarch64-linux-gnu/qt5/',
    '/usr/lib/mips64el-linux-gnu/qt5',
    '/usr/lib/loongarch64-linux-gnu/qt5/',
    '/usr/lib/x86_64-linux-gnu/qt5/'
]

# 定义内置需要分析 Qt Plugins 列表
QT_PLUGINS_LIST = [
    'bearer',
    # 'designer',
    'egldeviceintegrations',
    'generic',
    'iconengines',
    'imageformats',
    'kf5',
    'platforminputcontexts',
    'platforms',
    'platformthemes',
    'sqldrivers',
    'styles',
    'xcbglintegrations'
]


def help():
    print('********************************************')
    print('')
    print('python3 pack.py -file path_to_app1 path_to_app2')
    print('python3 pack.py -file path_to_app1 path_to_app2 -dest copy_deps_file_to_dir -qt_lib true -qt_plugin true')
    print('')
    print('********************************************')


if __name__ == '__main__':
    print('开始分析')
    current = os.path.abspath(os.path.dirname(__file__))
    if current not in sys.path:
        sys.path.append(current)

    if len(sys.argv) == 1:
        help()
        sys.exit()

    parser = argparse.ArgumentParser()
    parser.add_argument('-file', '-file', nargs='+', default=[], help='被分析文件')
    parser.add_argument('-dest', '-dest', default='./qt5', help='复制依赖文件到 dest 目录')
    parser.add_argument('-qt_lib', '-qt_lib', default='false', help='是否仅复制 Qt lib')
    parser.add_argument('-qt_plugin', '-qt_plugin', default='true', help='是否复制 Qt plugins 及依赖')

    args = parser.parse_args()
    if not isinstance(args.file, list):
        help()
        sys.exit()

    if len(args.file) == 0:
        help()
        sys.exit()

    dest = os.path.abspath(args.dest)

    if dest == '':
        help()
        sys.exit()

    import fs
    import ldd
    import utils

    # 先删除依赖文件夹
    if os.path.exists(dest):
        if not fs.remove_dir(dest):
            print('删除文件夹失败,path={0}'.format(dest))
            sys.exit()

    # 分析主程序依赖
    start = time.time()
    print('开始分析主程序依赖')
    deps = ldd.analyse(args.file)
    print('分析主程序依赖完成')
    span = (time.time() - start) * 1000.0

    # 只复制 qt lib
    args.qt_lib = utils.convert_bool(args.qt_lib)
    if args.qt_lib:
        deps = [item for item in deps if item.find('libQt5') >= 0]

    # 打印信息
    total = 0
    deps.sort()
    for dir_name in deps:
        stat = os.stat(dir_name)
        total += stat.st_size
    size = total / (1024 * 1024)
    print('用时 {0} ms,主程序依赖 {1} 个,大小 {2} MB'.format(span, len(deps), size))

    # 复制程序依赖
    print('开始复制主程序依赖')
    libs = os.path.join(dest, 'lib')
    if not fs.copy_file_dir(deps, libs, False):
        fs.remove_dir(dest)
        print('复制主程序依赖失败')
        sys.exit()
    print('复制主程序依赖完成')

    # 复制 webengine
    web_engine = [item for item in deps if item.find('WebEngine') != -1]
    if len(web_engine) > 0:
        # 复制 libexec
        for dir_name in QT_INSTALL_DIR:
            exec = os.path.join(dir_name, 'libexec')
            if os.path.exists(exec):
                if fs.copy_dir(exec, os.path.join(dest, 'libexec'), True):
                    print('复制 libexec 文件夹,成功')
                else:
                    print('复制 libexec 文件夹,失败')

        # 复制 resources
        if fs.copy_dir('/usr/share/qt5/resources', os.path.join(dest, 'resources'), True):
            print('复制 resources 文件夹,成功')
        else:
            print('复制 resources 文件夹,失败')

        # 复制 resources 到 libexec
        if fs.copy_file_dir(fs.ls_dir('/usr/share/qt5/resources'), os.path.join(dest, 'libexec'), False):
            print('复制 resources 到 libexec,成功')
        else:
            print('复制 resources 到 libexec,失败')

        # 复制 translations
        if fs.copy_dir(
                '/usr/share/qt5/translations/qtwebengine_locales',
                os.path.join(dest, 'libexec', 'qtwebengine_locales'),
                False
        ):
            print('复制 qtwebengine_locales 到 libexec,成功')
        else:
            print('复制 qtwebengine_locales 到 libexec,失败')

        # 复制 translations
        if fs.copy_dir('/usr/share/qt5/translations', os.path.join(dest, 'translations'), True):
            print('复制 translations 文件夹,成功')
        else:
            print('复制 translations 文件夹,失败')

    # 是否分析 Qt plugins 目录
    if not utils.convert_bool(args.qt_plugin):
        print('分析完成')
        sys.exit()

    error = False
    print('')
    print('开始分析 Qt 插件')
    for dir_name in QT_INSTALL_DIR:
        if not os.path.exists(dir_name):
            continue

        for plugin_name in QT_PLUGINS_LIST:
            plugin_src = os.path.join(dir_name, 'plugins', plugin_name)
            if not os.path.exists(plugin_src):
                print('不存在插件 {0}'.format(plugin_name))
                continue

            print('')
            print('开始分析 {0} 插件依赖'.format(plugin_name))
            start = time.time()
            deps = fs.ls_dir(plugin_src)
            deps = ldd.analyse(deps)
            print('分析 {0} 插件依赖完成'.format(plugin_name))
            span = (time.time() - start) * 1000.0
            total = 0
            for item in deps:
                stat = os.stat(item)
                total += stat.st_size
            size = total / (1024 * 1024)
            print('用时 {0} ms,分析 {1} 插件依赖 {2} 个,大小 {3} MB'.format(span, plugin_name, len(deps), size))

            if not fs.copy_file_dir(deps, libs, False):
                error = True
                print('复制 {0} 插件依赖到 lib 目录失败'.format(plugin_name))
                break
            else:
                print('复制 {0} 插件依赖到 lib 目录完成'.format(plugin_name))

            plugin_dest = os.path.join(dest, 'plugins', plugin_name)
            if not fs.copy_dir(plugin_src, plugin_dest):
                error = True
                print('复制 {0} 插件到 plugins 目录失败'.format(plugin_name))
                break
            else:
                print('复制 {0} 插件到 plugins 目录完成'.format(plugin_name))

        if error:
            break

    if error:
        fs.remove_dir(dest)
        print('分析失败')
    else:
        print('分析完成')
